home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-25 | 28.8 KB | 1,119 lines | [TEXT/MPS ] |
- // Copyright ©1994 Apple Computer, Inc.
- // Author: John Powers
- // Date: 25-Jul-94
-
- // UDocMo.cp
- // This file contains the documents and the objects that go
- // into the document window.
-
- #ifndef __UDOCMO__
- #include "UDocMo.h"
- #endif
-
- // Segment
-
- #pragma segment Main
-
- // ------------------------------------------------------------------------
- // TDocArt::DrawProc
- // Called by DeviceLoop.
- // A static function. Must be in a resident segment, locked and unpurgeable.
- // Because it's static, it cannot access object member variables directly.
- // We use the document window passed in userData to access its variables.
- pascal void
- TDocArt::DrawProc(short depth, short /*deviceFlags*/,
- GDHandle hTargetDevice,
- long userData)
- {
- // Get the document window from userData.
- TDocArt* theDocObject = (TDocArt*) userData;
- // Use depth of 1 if we have a computer without CQD.
- depth = (hTargetDevice==NULL)?1:depth;
- // Draw our objects.
- for(short i=0; i<theDocObject->fArtCnt; i++)
- ((TArt**)(*theDocObject->fhArt))[i]->Draw(depth);
- };
-
- // Segment
-
- #pragma segment MoG1
-
- // =========================================================================
- // TDocArt : TDoc : TDocument
- // ------------------------------------------------------------------------
- // TDocArt::TDocArt
- // Document window constructor.
- // Creates the window contents (TArt objects).
- TDocArt::TDocArt(short resID) : TDoc(resID)
- {
- this->fArtResId = 0;
- this->fArtCnt = 0;
- this->fIsCollision = false;
- this->fCollisionEvent = 0;
- this->fWantReset = false;
- this->fWantShuffle = false;
- this->fWantCollision = false;
- this->fhArt = nil;
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::~TDocArt
- // Document window destructor.
- // Deletes the window contents (TArt objects).
- TDocArt::~TDocArt()
- {
- if(this->fArtCnt)
- {
- for(short i=0; i<this->fArtCnt; i++)
- delete ((TArt**)(*this->fhArt))[i];
- DisposeHandle(this->fhArt);
- }
- if(this->fOffScreen)
- {
- delete this->fOffScreen;
- }
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::DoContent
- // The localMouse is in the content portion of the window.
- // Check to see if it's on any art objects.
- void
- TDocArt::DoContent(EventRecord* pEvent)
- {
- Rect drawRect;
- TArt* artObj;
- Point localMouse = pEvent->where;
- GlobalToLocal(&localMouse);
- for(short i=0; i<this->fArtCnt; i++)
- {
- artObj = ((TArt**)(*this->fhArt))[i];
- artObj->GetDrawRect(&drawRect);
- if(PtInRect(localMouse, &drawRect))
- {
- if(this->IsThisKeyDown(kCommandKey))
- {
- // Command key down.
- // Startup the guide topic for this art object.
- if(gAGuideAvailable)
- {
- // Get preset guide database file from app.
- FSSpec fileSpec;
- this->fApp->GetFile(fileSpec);
- if(fileSpec.name[0]>0)
- {
- SetCursor(*GetCursor(watchCursor));
- // Open database.
- AGRefNum refNum;
- AlertIfError(AGOpenWithSequence(&fileSpec,
- 0, nil,
- artObj->GetSequenceID(),
- &refNum));
- // Set refNum for app.
- this->fApp->SetRefNum(refNum);
- SetCursor(&qd.arrow);
- }
- }
- }
- else if(artObj->IsMoveable())
- {
- // Mouse down in our art and no key, track it.
- this->DragArt(artObj);
- }
- // No need to check other art objects.
- break;
- }
- }
- if(this->fIsCollision)
- {
- // There was a collision, send the event if it exists.
- if(gAGuideAvailable && this->fCollisionEvent)
- {
- AGRefNum refNum;
- this->fApp->GetRefNum(refNum);
- AGGeneral(refNum, this->fCollisionEvent);
- }
- // Reset collision flag so that we don't keep sending
- // the event every time we click in the window.
- this->fIsCollision = false;
- }
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::DoIdle
- // Do any action required during the idle processing.
- //
- void
- TDocArt::DoIdle()
- {
- if(this->fWantReset)
- {
- this->Reset();
- this->fWantReset = false;
- }
- if(this->fWantShuffle)
- {
- this->Shuffle();
- this->fWantShuffle = false;
- }
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::DragArt
- // Track the mouseDown by dragging the art object.
- // The art object is not allowed to overlap another art object.
- void
- TDocArt::DragArt(TArt* theArt)
- {
- Rect drawRect;
- Rect eraseRectV;
- Rect eraseRectH;
- Point oldLoc;
- Point newLoc;
- short deltaV;
- short deltaH;
- // Get a starting point for the mouseDown location.
- GetMouse(&oldLoc);
- // We may have been Coach-marked, the mouse-down
- // will erase us along with the Coach mark.
- // Let's refresh ourselves before moving.
- theArt->Draw();
- theArt->GetDrawRect(&drawRect);
- // Save current window "picture" off screen.
- this->DrawOff(theArt);
- // Track mouse.
- do
- {
- GetMouse(&newLoc);
- if(PtInRect(newLoc, &drawRect)
- && (newLoc.v!=oldLoc.v || newLoc.h!=oldLoc.h))
- {
- // The mouse has moved, move the art.
- deltaV = newLoc.v - oldLoc.v;
- deltaH = newLoc.h - oldLoc.h;
- // Save the current location.
- eraseRectV = eraseRectH = drawRect;
- // Proposed rect for art object.
- OffsetRect(&drawRect, deltaH, deltaV);
- // Cannot go outside of window boundaries
- if(this->IsOutsideWindow(&drawRect))
- {
- // Set drawRect to current position.
- theArt->GetDrawRect(&drawRect);
- }
- // Move if it doesn't overlap with another art object.
- else if(this->IsCollision(theArt, &drawRect))
- {
- // Oops, a collision; don't move.
- this->fIsCollision = true;
- // Set drawRect to current position.
- theArt->GetDrawRect(&drawRect);
- // Avoid "springing" effect.
- oldLoc = newLoc;
- }
- else
- {
- // No collision, move.
- this->fIsCollision = false;
- // Sometimes we move more than one pixel.
- // Erase the area left behind.
- if(deltaV>0)
- {
- // Moving down.
- eraseRectV.bottom = eraseRectV.top+deltaV;
- this->fOffScreen->CopyOffToOn(eraseRectV);
- }
- else if(deltaV<0)
- {
- // Moving up.
- eraseRectV.top = eraseRectV.bottom+deltaV;
- this->fOffScreen->CopyOffToOn(eraseRectV);
- }
- if(deltaH>0)
- {
- // Moving to the right.
- eraseRectH.right = eraseRectH.left+deltaH;
- this->fOffScreen->CopyOffToOn(eraseRectH);
- }
- else if(deltaH<0)
- {
- // Moving to the left.
- eraseRectH.left = eraseRectH.right+deltaH;
- this->fOffScreen->CopyOffToOn(eraseRectH);
- }
- // Set new rect and redraw.
- theArt->SetDrawRect(&drawRect);
- theArt->Draw();
- oldLoc = newLoc;
- }
- }
- }
- while (StillDown());
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::Draw
- // Document window.
- // Within BeginUpdate/EndUpdate.
- //
- // We set the port because the port defaults to the frontmost window.
- // We may not be the frontmost window when the update occurs.
- //
- void
- TDocArt::Draw()
- {
- // Setup and do DeviceLoop drawing.
- // Pass the document window in userData.
- long userData=(long)this;
- DeviceLoopFlags flags=0;
- SetPort(this->fDocWindow);
- DeviceLoop(this->fDocWindow->visRgn, TDocArt::DrawProc, userData, flags);
- };
-
- // ------------------------------------------------------------------------
- // TDocArt::DrawOff
- // Draw window contents to off-screen port.
- // Don't draw exceptArt (can be nil).
- //
- void
- TDocArt::DrawOff(TArt* exceptArt)
- {
- TArt* theArt;
- // Prepare off-screen world for drawing.
- this->fOffScreen->PrepareForDrawing();
- // Draw our objects in the off-screen port.
- for(short i=0; i<this->fArtCnt; i++)
- {
- theArt = ((TArt**)(*this->fhArt))[i];
- if(theArt!=exceptArt)
- {
- theArt->Draw();
- }
- }
- // Finished drawing in off-screen world.
- this->fOffScreen->DoneDrawing();
- };
-
- // ------------------------------------------------------------------------
- // TDocArt::GetLocation
- // Get the Rect of the named object.
- // Return true if the object is found.
- //
- // If two names, separated by a dash (-), are given,
- // the union of the named objects will be returned.
- //
- Boolean
- TDocArt::GetLocation(Ptr pNameIn, Rect* pRect)
- {
- Boolean result=true;
- char pNameLocal[64];
- Ptr pName1=pNameLocal;
- Ptr pName2;
-
- // Split pNameIn into pName1 and pName2.
-
- // Copy first name to pNameLoc (pName1).
- while(*pNameIn && *pNameIn!='-')
- *pName1++ = *pNameIn++;
- // Set terminator for first name at delimiter.
- *pName1 = 0;
- // Reset first name to the beginning.
- pName1 = pNameLocal;
- // If delimiter, then set pName2 to second name.
- // Otherwise, set pName2 to point to null.
- if(*pNameIn)
- pName2 = pNameIn+1;
- else
- pName2 = pNameIn;
-
- // Compare first name with known objects.
-
- char artName[32];
- Rect rect1;
- Rect rect2;
- Boolean found1=false;
- Boolean found2=false;
-
- for(short i=0; i<this->fArtCnt; i++)
- {
- // Get the name of the i-th art object.
- ((TArt**)(*this->fhArt))[i]->GetName(artName);
- // See if it matches the first name.
- if(*pName1 && !found1)
- {
- if(isEqualString(pName1, artName))
- {
- ((TArt**)(*this->fhArt))[i]->GetDrawRect(&rect1);
- found1 = true;
- }
- }
- // See if it matches the second name.
- if(*pName2 && !found2)
- {
- if(isEqualString(pName2, artName))
- {
- ((TArt**)(*this->fhArt))[i]->GetDrawRect(&rect2);
- found2 = true;
- }
- }
- }
- // Form union if both names found.
- if(found1 && found2)
- UnionRect(&rect1, &rect2, pRect);
- else if(found1)
- *pRect = rect1;
- else if(found2)
- *pRect = rect2;
- else
- result = false;
-
- return result;
- };
-
- // ------------------------------------------------------------------------
- // TDocArt::Init
- // Document window initialization.
- // Creates the window contents (TArt objects).
- // The art objects are linked to the window
- // by sharing the same resource ID.
- // The art object data is set in the LoadArt function.
- // We separate the functions so that LoadArt
- // can be used for Init and for resetting the objects.
- // The window pointer is set in the document initialization.
- // Return any error.
- //
- OSErr
- TDocArt::Init(short resID)
- {
- OSErr err=noErr;
- TArt* artObj;
- // Save our resource id (for resetting.)
- this->fArtResId = resID;
- // Clear our member variables.
- this->fArtCnt = 0;
- this->fhArt = nil;
- // Get the list of art objects.
- // Use local variables for efficiency.
- Handle hArt = GetResource(kResArtObjects, this->fArtResId);
- if(hArt)
- {
- // Better lock this baby down or it will move.
- HLock(hArt);
- // Get the number of art objects.
- ArtListPtr pArtList = (ArtListPtr) *hArt;
- short artCnt = pArtList->artCnt;
- // Get some memory to hold these babies.
- Handle hArtList = NewHandle(artCnt*sizeof(ArtType));
- if(hArtList)
- {
- // Instantiate each art object and add to list.
- for(short i=0; i<artCnt; i++)
- {
- artObj = new TArt;
- ((TArt**)(*hArtList))[i] = artObj;
- }
- // All okay, update member variables.
- this->fhArt = hArtList;
- this->fArtCnt = artCnt;
- // Load the art objects.
- this->LoadArt();
- }
- HUnlock(hArt);
- }
- this->fOffScreen = new TBitMapColor;
- if(this->fOffScreen)
- err = this->fOffScreen->Init();
- return err;
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::IsCollision
- //
- // Tests to see if the proposed rectangle for theArt intersects with any
- // of the remaining art objects. Returns true or false.
- // They must be on the same layer to collide.
- //
- Boolean
- TDocArt::IsCollision(TArt* theArt, Rect* proposedArtRect)
- {
- Rect testRect;
- Rect dstRect;
- TArt* theOtherArt;
- for(short i=0; i<this->fArtCnt; i++)
- {
- theOtherArt = ((TArt**)(*this->fhArt))[i];
- if(theOtherArt!=theArt)
- {
- if(this->IsSameLayer(theArt, theOtherArt))
- {
- theOtherArt->GetDrawRect(&testRect);
- if(SectRect(proposedArtRect, &testRect, &dstRect))
- {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::IsOutsideWindow
- // Return true if any portion of the art object
- // is outside of the window content area.
- //
- // Calculate the intersection of the proposedArtRect with the portRect.
- // If the proposedArtRect is entirely within the portRect, the
- // intersection will be equal to the proposedArtRect.
- //
- Boolean
- TDocArt::IsOutsideWindow(Rect* proposedArtRect)
- {
- Rect insideRect;
- SectRect(proposedArtRect, &this->fDocWindow->portRect, &insideRect);
- return !EqualRect(proposedArtRect, &insideRect);
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::IsSameLayer
- // Return true if the art objects are at the same layer.
- Boolean
- TDocArt::IsSameLayer(TArt* theArt, TArt* theOtherArt)
- {
- return theArt->GetLayer()==theOtherArt->GetLayer();
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::Reset
- // Reset the window.
- // In this case, we erase the window and redraw its contents.
- //
- void
- TDocArt::Reset()
- {
- this->Erase();
- this->LoadArt();
- this->Invalidate();
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::LoadArt
- // Art object initialization.
- // The memory was allocated in the Init function.
- // We separate the functions so that LoadArt
- // can be used for Init and for resetting the objects.
- void
- TDocArt::LoadArt()
- {
- // Get the list of art objects.
- Handle hArt = GetResource(kResArtObjects, this->fArtResId);
- if(hArt)
- {
- // Better lock this baby down or it will move.
- HLock(hArt);
- // Get the number of art objects.
- ArtListPtr pArtList = (ArtListPtr) *hArt;
- // Instantiate each art object and add to list.
- for(short i=0; i<this->fArtCnt; i++)
- {
- ((TArt**)(*this->fhArt))[i]->Init(pArtList->art[i]);
- }
- HUnlock(hArt);
- }
- }
-
- // ------------------------------------------------------------------------
- // TDocArt::Shuffle
- // Shuffle the location of the art objects.
- // We do this by swapping each of the objects
- // with another object selected at random.
- void
- TDocArt::Shuffle()
- {
- short randomNum;
- short iA;
- short iB;
- TArt* artA;
- TArt* artB;
- if(this->fArtCnt<=0)
- return;
- // Use this->LoadArt() to return all art to its normal location.
- this->Erase();
- // Seed random number generator.
- GetDateTime((unsigned long *)&qd.randSeed);
- // Step through each art object.
- for(iA=0; iA<this->fArtCnt; iA++)
- {
- artA = ((TArt**)(*this->fhArt))[iA];
- // Positive index from 0 to this->fArtCnt-1.
- randomNum = Random();
- randomNum = (randomNum<0)?-randomNum:randomNum;
- iB = randomNum/(32767/this->fArtCnt);
- #if __DebugShuffle__
- Str255 msgStr;
- NumToString(iB, msgStr);
- if(iB<0)
- {
- pcat(msgStr, "\p is less than 0.");
- DebugStr(msgStr);
- iB = 0;
- }
- else if(iB>=this->fArtCnt)
- {
- Str255 numStr;
- pcat(msgStr, "\p is equal to or greater than ");
- NumToString(this->fArtCnt, numStr);
- pcat(msgStr, numStr);
- DebugStr(msgStr);
- iB = this->fArtCnt-1;
- }
- #endif
- artB = ((TArt**)(*this->fhArt))[iB];
- if(artA!=artB)
- {
- // Swap locations.
- Rect drawRectA;
- Rect drawRectB;
- artA->GetDrawRect(&drawRectA);
- artB->GetDrawRect(&drawRectB);
- artA->SetDrawRect(&drawRectB);
- artB->SetDrawRect(&drawRectA);
- }
- }
- // Let's draw all the art in its new location.
- this->Invalidate();
- }
-
- // =========================================================================
- // TDocFB : TDoc : TDocument
- // ------------------------------------------------------------------------
- // TDocFB::TDocFB
- // Document window constructor.
- // This empty constructor passes the resID to TDoc.
- //
- TDocFB::TDocFB(short resID) : TDoc(resID)
- {
- this->fhControl = nil;
- }
-
- // ------------------------------------------------------------------------
- // TDocFB::~TDocFB
- // Document window destructor.
- //
- TDocFB::~TDocFB()
- {
- if(this->fhControl!=nil)
- DisposeControl(this->fhControl);
- }
-
- // ------------------------------------------------------------------------
- // TDocFB::DoContent
- // The mouseDown is in the content portion of the window.
- // Check to see if it's on a control.
- //
- void
- TDocFB::DoContent(EventRecord* pEvent)
- {
- ControlHandle whichControl;
- Point localMouse = pEvent->where;
- GlobalToLocal(&localMouse);
- short partCode = FindControl(localMouse, this->fDocWindow, &whichControl);
- if(partCode!=0)
- {
- if(TrackControl(whichControl, localMouse, nil)==partCode)
- {
- // The control was controlled.
- // Startup the preset database.
- if(gAGuideAvailable)
- {
- // Get preset guide database file from app.
- FSSpec fileSpec;
- this->fApp->GetFile(fileSpec);
- if(fileSpec.name[0]>0)
- {
- SetCursor(*GetCursor(watchCursor));
- // Open database.
- AGRefNum refNum;
- AlertIfError(AGOpen(&fileSpec, 0, nil, &refNum));
- // Set refNum for app.
- this->fApp->SetRefNum(refNum);
- SetCursor(&qd.arrow);
- }
- }
- }
- }
- };
-
- // ------------------------------------------------------------------------
- // TDocFB::Draw
- //
- // We set the port because the port defaults to the frontmost window.
- // We may not be the frontmost window when the update occurs.
- //
- void
- TDocFB::Draw()
- {
- Str255 string;
- SetPort(this->fDocWindow);
- TextFont(monaco);
- TextSize(9);
- TextMode(patCopy);
- // Context check
- MoveTo(kLocH, kLocCCV);
- GetIndString(string, kFeedbackStrId, kStrContext);
- DrawString(string);
- GetPen(&this->fLoc[dataCC]);
- // Coach mark
- MoveTo(kLocH, kLocCHV);
- GetIndString(string, kFeedbackStrId, kStrCoach);
- DrawString(string);
- GetPen(&this->fLoc[dataCH]);
- // Event
- MoveTo(kLocH, kLocEVV);
- GetIndString(string, kFeedbackStrId, kStrEvent);
- DrawString(string);
- GetPen(&this->fLoc[dataEV]);
- // Miscellaneous
- MoveTo(kLocH, kLocMSV);
- GetIndString(string, kFeedbackStrId, kStrMisc);
- DrawString(string);
- GetPen(&this->fLoc[dataTP]);
- // Control
- DrawControls(this->fDocWindow);
- }
-
- // ------------------------------------------------------------------------
- // TDocFB::DrawData
- //
- // We set the port because the port defaults to the frontmost window.
- // We may not be the frontmost window when the update occurs.
- //
- // The IM QuickDraw documentation is not clear on whether to
- // use PenMode or TextMode. We are passing patCopy to draw
- // and patBic to erase in a TextMode procedure, not srcOr and srcBic
- // as the documentation would lead you to believe. Nor does the
- // use of patCopy and patBic with PenMode work. Our usage works.
- //
- void
- TDocFB::DrawData(Str255 string, short mode, short whichData)
- {
- SetPort(this->fDocWindow);
- TextMode(mode);
- MoveTo(this->fLoc[whichData].h, this->fLoc[whichData].v);
- DrawString(string);
- }
-
- // ------------------------------------------------------------------------
- // TDocFB::Init
- //
- OSErr
- TDocFB::Init()
- {
- OSErr err=noErr;
- this->fhControl = GetNewControl(kAssistantCntlID, this->fDocWindow);
- if(this->fhControl)
- {
- // Center control.
- short winWidth = this->fDocWindow->portRect.right
- - this->fDocWindow->portRect.left;
- short ctrlWidth = (**this->fhControl).contrlRect.right
- - (**this->fhControl).contrlRect.left;
- short ctrlLeft = (winWidth - ctrlWidth) / 2;
- MoveControl(this->fhControl, ctrlLeft, kLocCTV);
- ShowControl(this->fhControl);
- }
- else
- err = kErrDocFBInitFailed;
- return err;
- };
-
- // =========================================================================
- // TArt
- // ------------------------------------------------------------------------
- // TArt::Draw
- // All art objects (PICT's) are drawn from here.
- // This is where we distinguish between B&W and color renderings
- // of TArt objects. The B&W rendering has a resource ID that
- // is kBWOffset larger than its color counterpart.
- // If the function can't find one version, it will try the other.
- void
- TArt::Draw(short depth)
- {
- // Don't draw empty art.
- if(this->fArt.pictId==0)
- return;
- this->fLastDepth = depth;
- PicHandle hPict;
- if(depth<8)
- {
- // Use B&W PICT.
- hPict = (PicHandle) GetResource('PICT', this->fArt.pictId+kBWOffset);
- if(!hPict)
- {
- // No B&W PICT, try color (may really be B&W).
- hPict = (PicHandle) GetResource('PICT', this->fArt.pictId);
- }
- }
- else
- {
- // Use color PICT.
- hPict = (PicHandle) GetResource('PICT', this->fArt.pictId);
- if(!hPict)
- {
- // No color PICT, try B&W.
- hPict = (PicHandle) GetResource('PICT', this->fArt.pictId+kBWOffset);
- }
- }
- if(hPict)
- {
- // We could have used the fDrawRect private member variable,
- // but we'll use the access function here.
- Rect theDrawRect;
- this->GetDrawRect(&theDrawRect);
- HLock((Handle) hPict);
- DrawPicture(hPict, &theDrawRect);
- HUnlock((Handle) hPict);
- }
- };
-
- // ------------------------------------------------------------------------
- // TArt::Draw
- // Draw at the depth used for the last call.
- void
- TArt::Draw()
- {
- this->Draw(this->fLastDepth);
- }
-
- // ------------------------------------------------------------------------
- void
- TArt::GetDrawRect(Rect* theRect)
- {
- *theRect = this->fDrawRect;
- }
-
- // ------------------------------------------------------------------------
- // TArt::GetName
- // Return the name of the art object by copying it to theName.
- void
- TArt::GetName(char* theName)
- {
- char* pArtName=this->fArt.name;
- while(*theName++=*pArtName++)
- ;
- }
-
- // ------------------------------------------------------------------------
- // TArt::Init
- // Initialize the art object.
- // Set it's PICT ID and drawing location.
- void
- TArt::Init(ArtType theArt)
- {
- // Save art object description.
- this->fArt = theArt;
- this->fLastDepth = 1;
- SetRect(&this->fDrawRect, 0, 0, 0, 0);
- // Normalize PICT to desired drawing location.
- PicHandle hPict = (PicHandle) GetResource('PICT', this->fArt.pictId);
- if(hPict)
- {
- // Get the original drawing rect.
- this->fDrawRect = (**hPict).picFrame;
- // Normalize rect to 0,0 in case the artist didn't.
- OffsetRect(&this->fDrawRect, -this->fDrawRect.left,
- -this->fDrawRect.top);
- // Move rect to loc.
- OffsetRect(&this->fDrawRect, this->fArt.locH, this->fArt.locV);
- }
- };
-
- // ------------------------------------------------------------------------
- void
- TArt::SetDrawRect(Rect* theRect)
- {
- this->fDrawRect = *theRect;
- }
-
- // =========================================================================
- // TBitMap
- // ------------------------------------------------------------------------
- TBitMap::TBitMap() // constructor
- {
- };
-
- // ------------------------------------------------------------------------
- TBitMap::~TBitMap() // destructor
- {
- };
-
- // =========================================================================
- // TBitMapBW-->TBitMap
- // ------------------------------------------------------------------------
- TBitMapBW::TBitMapBW() // constructor
- {
- this->fOffPort = nil;
- };
-
- // ------------------------------------------------------------------------
- TBitMapBW::~TBitMapBW() // destructor
- {
- if(this->fOffPort)
- {
- ClosePort(this->fOffPort);
- DisposPtr(this->fOffPort->portBits.baseAddr);
- DisposPtr((Ptr)this->fOffPort);
- }
- };
-
- // ------------------------------------------------------------------------
- // TBitMapBW::CopyOffToOn
- // Copy all of off-screen port to on-screen port.
- void
- TBitMapBW::CopyOffToOn()
- {
- this->CopyOffToOn(this->fOffRect);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapBW::CopyOffToOn
- // Copy a rect from off-screen port to on-screen port.
- void
- TBitMapBW::CopyOffToOn(Rect& rectToCopy)
- {
- GrafPtr onPort;
-
- GetPort(&onPort);
- CopyBits( &this->fOffPort->portBits,
- &onPort->portBits,
- &rectToCopy,
- &rectToCopy, srcCopy, nil);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapBW::CopyOnToOff
- // Copy all of on-screen port to off-screen port.
- void
- TBitMapBW::CopyOnToOff()
- {
- this->CopyOnToOff(this->fOffRect);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapBW::CopyOnToOff
- // Copy a rect from on-screen port to off-screen port.
- void
- TBitMapBW::CopyOnToOff(Rect& rectToCopy)
- {
- GrafPtr onPort;
-
- GetPort(&onPort);
- CopyBits( &onPort->portBits,
- &this->fOffPort->portBits,
- &rectToCopy,
- &rectToCopy, srcCopy, nil);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapBW::DoneDrawing
- void
- TBitMapBW::DoneDrawing()
- {
- SetPort(this->fSavedOnPort);
- }
-
- // ------------------------------------------------------------------------
- // TBitMapBW::Init
- // Build bit map for an offscreen port equal to the current grafPort.
- OSErr
- TBitMapBW::Init()
- {
- OSErr err;
- Rect offRect;
- GrafPtr onPort,
- newOffPort;
-
- GetPort(&onPort);
- // Our off-screen rect exactly duplicates the on-screen rect.
- offRect = onPort->portRect;
- // Normalize off-screen rect.
- OffsetRect(&offRect, -offRect.left, -offRect.top);
- newOffPort = (GrafPtr) NewPtr(sizeof(GrafPort));
- if((err=MemError())!=noErr)
- return err;
- OpenPort(newOffPort);
- newOffPort->portRect = offRect;
- newOffPort->portBits.bounds = offRect;
- RectRgn(newOffPort->clipRgn, &offRect);
- RectRgn(newOffPort->visRgn, &offRect);
- // Rect is normalized so we only need to use its right and bottom.
- newOffPort->portBits.rowBytes = ((offRect.right + 15) >> 4) << 1;
- newOffPort->portBits.baseAddr = NewPtr(newOffPort->portBits.rowBytes * (long)offRect.bottom);
- if((err=MemError())!=noErr) {
- SetPort(onPort);
- ClosePort(newOffPort);
- DisposPtr((Ptr)newOffPort);
- return err;
- }
- // Clear out new offScreen rect.
- EraseRect(&offRect);
- // Save key variables.
- this->fOffRect = offRect;
- this->fOffPort = newOffPort;
- // Restore to screen port.
- SetPort(onPort);
- return noErr;
- };
-
- // ------------------------------------------------------------------------
- // TBitMapBW::PrepareForDrawing
- // Set the port to this bit map and erase it.
- void
- TBitMapBW::PrepareForDrawing()
- {
- GetPort(&this->fSavedOnPort);
- SetPort(this->fOffPort);
- EraseRect(&this->fOffRect);
- }
-
- // =========================================================================
- // TBitMapColor-->TBitMap
- // ------------------------------------------------------------------------
- TBitMapColor::TBitMapColor() // constructor
- {
- this->fOffGWorld = nil;
- };
-
- // ------------------------------------------------------------------------
- TBitMapColor::~TBitMapColor() // destructor
- {
- if(this->fOffGWorld)
- {
- DisposeGWorld(this->fOffGWorld);
- }
- };
-
- // ------------------------------------------------------------------------
- // TBitMapColor::CopyOffToOn
- // Copy all of off-screen port to on-screen port.
- void
- TBitMapColor::CopyOffToOn()
- {
- this->CopyOffToOn(this->fOffRect);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapColor::CopyOffToOn
- // Copy a rect from off-screen port to on-screen port.
- void
- TBitMapColor::CopyOffToOn(Rect& rectToCopy)
- {
- CGrafPtr onPort;
- GDHandle onDevice;
-
- GetGWorld(&onPort, &onDevice);
- PixMapHandle hOffPixMap = GetGWorldPixMap(this->fOffGWorld);
- LockPixels(hOffPixMap);
- CopyBits( &**(BitMap**)hOffPixMap,
- &**(BitMap**)onPort->portPixMap,
- &rectToCopy,
- &rectToCopy,
- srcCopy, nil);
- UnlockPixels(hOffPixMap);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapColor::CopyOnToOff
- // Copy all of on-screen port to off-screen port.
- void
- TBitMapColor::CopyOnToOff()
- {
- this->CopyOnToOff(this->fOffRect);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapColor::CopyOnToOff
- // Copy a rect from on-screen port to off-screen port.
- void
- TBitMapColor::CopyOnToOff(Rect& rectToCopy)
- {
- CGrafPtr onPort;
- GDHandle onDevice;
-
- GetGWorld(&onPort, &onDevice);
- PixMapHandle hOffPixMap = GetGWorldPixMap(this->fOffGWorld);
- LockPixels(hOffPixMap);
- CopyBits( &**(BitMap**)onPort->portPixMap,
- &**(BitMap**)hOffPixMap,
- &rectToCopy,
- &rectToCopy,
- srcCopy, nil);
- UnlockPixels(hOffPixMap);
- };
-
- // ------------------------------------------------------------------------
- // TBitMapColor::DoneDrawing
- void
- TBitMapColor::DoneDrawing()
- {
- UnlockPixels(GetGWorldPixMap(this->fOffGWorld));
- SetGWorld(this->fSavedOnPort, this->fSavedOnDevice);
- }
-
- // ------------------------------------------------------------------------
- // TBitMapColor::Init
- // Build bit map for an offscreen port equal to the current grafPort.
- OSErr
- TBitMapColor::Init()
- {
- short pixelDepth=8;
- RGBColor myRGBColor;
- CGrafPtr onPort;
- GDHandle onDevice;
- GWorldPtr offGWorld;
- Rect offRect;
-
- GetGWorld(&onPort, &onDevice);
- offRect = onPort->portRect;
- // Normalize off-screen rect.
- OffsetRect(&offRect, -offRect.left, -offRect.top);
- // we have created a world
- OSErr err = NewGWorld(&offGWorld, pixelDepth, &offRect, nil, nil, 0);
- if(err!=noErr)
- return err;
- // Everything from here on is done off screen.
- SetGWorld(offGWorld, nil);
- // set the background color to white
- myRGBColor.red = 0xFFFF;
- myRGBColor.blue = 0xFFFF;
- myRGBColor.green = 0xFFFF;
- RGBBackColor(&myRGBColor);
- // set the foreground color to black
- myRGBColor.red = 0;
- myRGBColor.blue = 0;
- myRGBColor.green = 0;
- RGBForeColor(&myRGBColor);
- // Clear out new offScreen rect.
- EraseRect(&offRect);
- // Save key variables.
- this->fOffRect = offRect;
- this->fOffGWorld = offGWorld;
- // Restore to on-screen GWorld.
- SetGWorld(onPort, onDevice);
- return noErr;
- };
-
- // ------------------------------------------------------------------------
- // TBitMapColor::PrepareForDrawing
- // Set the port to this bit map and erase it.
- void
- TBitMapColor::PrepareForDrawing()
- {
- GetGWorld(&this->fSavedOnPort, &this->fSavedOnDevice);
- SetGWorld(this->fOffGWorld, nil);
- // We ignore any failure of LockPixels.
- (void) LockPixels(GetGWorldPixMap(this->fOffGWorld));
- EraseRect(&this->fOffRect);
- }
-
-